package com.wisnews.util;

import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.toolkit.StringUtils;
import com.baomidou.mybatisplus.core.toolkit.Wrappers;
import com.wisnews.pojo.sec.entity.ParameterConfig;
import com.wisnews.service.CrawlDataAutoSchedService;
import com.wisnews.service.sec.IParameterConfigService;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.scheduling.annotation.Scheduled;
import org.springframework.scheduling.annotation.SchedulingConfigurer;
import org.springframework.scheduling.config.ScheduledTaskRegistrar;
import org.springframework.scheduling.support.CronTrigger;
import org.springframework.stereotype.Component;

import javax.annotation.PostConstruct;

/**
 * @Description：
 * @Author: yuyd
 * @Email: yyd8358@foxmail.com
 * @Since: 2021-05-04 11:50
 * @Version
 */
@Component
@Slf4j
public class TimedTask implements SchedulingConfigurer {

    @Autowired
    private CrawlDataAutoSchedService crawlDataAutoSchedService;

    @Autowired
    private IParameterConfigService parameterConfigService;

    private String cronExpression;

    @Override
    public void configureTasks(ScheduledTaskRegistrar scheduledTaskRegistrar) {
        scheduledTaskRegistrar.addTriggerTask(() -> {
            //判断定时任务是否生效,不生效不执行定时任务
            if (!isExecuteScheduling()) {
                return;
            }
            //定时任务调度，可以增加其他定时任务。
            log.error("定时任务生效，后台执行开始！cronExpression="+cronExpression);
            //创建一个新线程去执行爬虫
            new Thread(() -> crawlDataAutoSchedService.crawlData()).start();
            //每次调度完成后，重新加载cron
            initCronConfig();
        }, triggerContext -> new CronTrigger(cronExpression).nextExecutionTime(triggerContext));

    }

    /**
     * @description: 根据数据库配置，判断是否指定定时任务。不影响传统方式调用
     * @param:
     * @return:
     * @author yuyd
     * @date: 2021/5/4 10:31
     */
    private Boolean isExecuteScheduling() {
        //读取参数表控制定时任务是否执行
        LambdaQueryWrapper<ParameterConfig> parameterConfigQueryWrapper = Wrappers.lambdaQuery();
        // TODO 开发环境使用 ***_dev 变量，不开启定时任务执行。上线需要修改
        parameterConfigQueryWrapper.eq(ParameterConfig::getParameterKey, "execute_scheduling_dev");
        ParameterConfig parameter = parameterConfigService.getOne(parameterConfigQueryWrapper);
        if (parameter != null && StringUtils.isNotBlank(parameter.getParameterValue()) && "1".equals(parameter.getParameterValue())) {
            //当数据库参数配置为"1"时，执行，其他不执行
            return true;
        }
        //默认不执行
        return false;
    }


    /**
     * @description: 读取数据库配置，初始化cron表达式。对象创建完成后，会执行。使用PostConstruct。每隔十分钟刷新一次cron表达式
     * @param:
     * @return:
     * @author yuyd
     * @date: 2021/5/4 10:42
     */
    @PostConstruct
    @Scheduled(cron = "0 0/10 * * * ?")
    public void initCronConfig() {
        //创建对象时访问参数表读取定时任务规则
        LambdaQueryWrapper<ParameterConfig> parameterConfigQueryWrapper = Wrappers.lambdaQuery();
        parameterConfigQueryWrapper.eq(ParameterConfig::getParameterKey, "cronExpression");
        ParameterConfig parameter = parameterConfigService.getOne(parameterConfigQueryWrapper);
        if (parameter == null || StringUtils.isBlank(parameter.getParameterValue())) {
            //如果参数表没有配置 定时任务表达式，使用默认规则。每十五分钟执行一次。
            this.cronExpression = "0 15 * * * ?";
        }
        this.cronExpression = parameter.getParameterValue();

    }

}
